package jsu.hx.lost.Service;

import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import jsu.hx.lost.Mapper.FindMapper;
import jsu.hx.lost.Mapper.LostMapper;
import jsu.hx.lost.Model.dto.FindItemDTO;
import jsu.hx.lost.Model.entity.LostItem;
import jsu.hx.lost.Model.dto.LostItemDTO;
import jsu.hx.lost.Model.entity.Notifications;
import jsu.hx.lost.Model.vo.PageResult;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

@Slf4j
@Service
public class LostItemService {

    @Autowired
    private LostMapper lostMapper;

    @Autowired
    private FileStorageService fileStorageService;
    // LostItemService.java 新增依赖注入和方法
    @Autowired
    private FindMapper findMapper;
    @Autowired
    private NotificationsService notificationsService;
    public List<LostItemDTO> getAllLostItems() {
        return lostMapper.selectLostItemDTOs();
    }

    public LostItemDTO getLostItemById(Long id) {
        return lostMapper.selectLostItemDTOById(id);
    }

    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> addLostItem(String itemName, String itemCategory, String lostLocation,String locate,
                                           Date lostTime, String detailedDescription, MultipartFile imageFile) {
        Map<String, Object> response = new HashMap<>();
        try {
            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
            Long userId = Long.parseLong(authentication.getPrincipal().toString());

            LostItem lostItem = buildLostItem(userId, itemName, itemCategory, lostLocation,locate,
                    lostTime, detailedDescription, imageFile);
            int result = lostMapper.insert(lostItem);

            if (result > 0) {
                checkFindItemMatches(lostItem);
                response.put("status", "success");
                response.put("data", lostItem.getId());
            } else {
                response.put("status", "error");
                response.put("message", "数据库插入失败");
            }
        } catch (Exception e) {
            handleException(response, e);
        }
        return response;
    }

    @Transactional
    public Map<String, Object> updateLostItem(Long id, MultipartFile imageFile, String itemName,
                                              String itemCategory, String lostLocation,String locate, Date lostTime,
                                              String detailedDescription) {
        Map<String, Object> response = new HashMap<>();
        String newImagePath = null;
        String oldImagePath = null;

        try {
            // 1. 获取原数据
            LostItem existingItem = lostMapper.selectById(id);
            if (existingItem == null || existingItem.getIsDeleted() == 1) {
                response.put("status", "error");
                response.put("message", "指定ID的记录不存在");
                return response;
            }
            oldImagePath = existingItem.getImage();

            // 2. 构建动态更新条件
            UpdateWrapper<LostItem> wrapper = new UpdateWrapper<LostItem>().eq("id", id);

            // 3. 文件上传（优先处理）
            if (imageFile != null && !imageFile.isEmpty()) {
                newImagePath = fileStorageService.saveImage(imageFile, "lost_items");
                wrapper.set("image", newImagePath);
            }

            // 4. 字段更新逻辑
            // 字符串字段：空字符串和null不更新
            updateFieldIfValid(wrapper, "item_name", itemName, existingItem.getItemName());
            updateFieldIfValid(wrapper, "item_category", itemCategory, existingItem.getItemCategory());
            updateFieldIfValid(wrapper, "lost_location", lostLocation, existingItem.getLostLocation());
            updateFieldIfValid(wrapper, "detailed_description", detailedDescription, existingItem.getDetailedDescription());
            updateFieldIfValid(wrapper, "locate", locate, existingItem.getLocate());
            // 时间字段：允许设置为null
            if (lostTime != null) {
                wrapper.set("lost_time", lostTime);
            }

            // 5. 执行数据库更新
            int result = lostMapper.update(null, wrapper);

            if (result > 0) {
                // 6. 成功时删除旧图片（保留默认图片）
                if (newImagePath != null && oldImagePath != null && !oldImagePath.isEmpty()) {
                    safeDeleteFile(oldImagePath);
                }
                response.put("status", "success");
                response.put("data", lostMapper.selectById(id));
            } else {
                // 7. 数据库失败时回滚新图片
                safeDeleteFile(newImagePath);
                response.put("status", "error");
                response.put("message", "更新操作未生效");
            }
        } catch (Exception e) {
            // 8. 异常时回滚新图片
            safeDeleteFile(newImagePath);
            handleException(response, e);
        }
        return response;
    }

    // 辅助方法：字段更新逻辑
    private void updateFieldIfValid(UpdateWrapper<LostItem> wrapper, String column, String newValue, String originalValue) {
        if (newValue != null) {
            // 空字符串不更新，非空字符串且与原值不同时更新
            if (StringUtils.hasText(newValue) && !newValue.equals(originalValue)) {
                wrapper.set(column, newValue);
            }
        }
    }

    // 安全删除文件（带异常捕获）
    private void safeDeleteFile(String filePath) {
        if (filePath != null && !filePath.isEmpty()) {
            try {
                fileStorageService.deleteOldImage(filePath);
            } catch (IOException e) {
                log.error("文件删除失败: {}", e.getMessage());
            }
        }
    }


    public String deleteLostItem(Long id) {
        UpdateWrapper<LostItem> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("id", id).set("is_deleted", 1);
        int result = lostMapper.update(null, updateWrapper);
        return result > 0 ? "Item deleted successfully" : "Failed to delete item";
    }

    public Map<String, Object> getMyLostItems() {
        Map<String, Object> response = new HashMap<>();
        try {
            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
            if (authentication == null || authentication.getPrincipal() == null) {
                response.put("status", "error");
                response.put("message", "用户未认证");
                return response;
            }

            Long userId = Long.parseLong(authentication.getPrincipal().toString());
            List<LostItemDTO> items = lostMapper.selectLostItemDTOsByUserId(userId);
            response.put("status", "success");
            response.put("data", items);
        } catch (Exception e) {
            handleException(response, e);
        }
        return response;
    }

    public List<LostItemDTO> fuzzySearch(String itemName, String lostLocation, Date lostTime,String username) {
        return lostMapper.selectByFuzzySearch(itemName, lostLocation, lostTime,username);
    }

    // LostItemService.java
    public PageResult<LostItemDTO> getLostItemsByPage(int page, int pageSize,
                                                      String itemName, String lostLocation, Date lostTime,
                                                      String username, String sortField, String sortOrder) {

        // 确保排序字段安全
        if (!"id".equalsIgnoreCase(sortField)) {
            sortField = "id";
        }
        if (!"ASC".equalsIgnoreCase(sortOrder) && !"DESC".equalsIgnoreCase(sortOrder)) {
            sortOrder = "DESC"; // 默认降序
        }

        // 计算偏移量
        int offset = (page - 1) * pageSize;

        // 调用Mapper
        List<LostItemDTO> items = lostMapper.selectLostItemDTOsByPage(
                offset, pageSize, itemName, lostLocation, lostTime,
                username, sortField, sortOrder
        );

        // 获取总数
        long total = lostMapper.selectLostItemTotalCount();

        return new PageResult<>(items, total, page, pageSize);
    }

    // 私有方法：构建LostItem对象
    private LostItem buildLostItem(Long userId, String itemName, String itemCategory, String lostLocation,String locate,
                                   Date lostTime, String detailedDescription, MultipartFile imageFile) throws IOException {
        LostItem lostItem = new LostItem();
        lostItem.setItemName(itemName);
        lostItem.setItemCategory(itemCategory);
        lostItem.setLostLocation(lostLocation);
        lostItem.setLocate(locate);
        lostItem.setLostTime(lostTime);
        lostItem.setDetailedDescription(detailedDescription);
        lostItem.setUserId(userId);
        lostItem.setCreatedAt(new Date());

        if (imageFile != null && !imageFile.isEmpty()) {
            String imagePath = fileStorageService.saveImage(imageFile, "lost_items");
            lostItem.setImage(imagePath);
        }
        return lostItem;
    }
    public List<LostItemDTO> getLatestLostItems(int limit) {
        return lostMapper.selectLatestLostItems(limit);
    }
    // 私有方法：构建UpdateWrapper
    private UpdateWrapper<LostItem> buildUpdateWrapper(Long id, MultipartFile imageFile, LostItem existingItem,
                                                       String itemName, String itemCategory, String lostLocation,
                                                       Date lostTime, String detailedDescription) throws IOException {
        UpdateWrapper<LostItem> wrapper = new UpdateWrapper<LostItem>().eq("id", id);

        if (imageFile != null && !imageFile.isEmpty()) {
            String newImagePath = fileStorageService.saveImage(imageFile, "lost_items");
            wrapper.set("image", newImagePath);
            fileStorageService.deleteOldImage(existingItem.getImage());
        }

        if (itemName != null) wrapper.set("item_name", StringUtils.hasText(itemName) ? itemName : null);
        if (itemCategory != null) wrapper.set("item_category", StringUtils.hasText(itemCategory) ? itemCategory : null);
        if (lostLocation != null) wrapper.set("lost_location", StringUtils.hasText(lostLocation) ? lostLocation : null);
        if (lostTime != null) wrapper.set("lost_time", lostTime);
        if (detailedDescription != null) wrapper.set("detailed_description", StringUtils.hasText(detailedDescription) ? detailedDescription : null);

        return wrapper;
    }

    // 私有方法：统一异常处理
    private void handleException(Map<String, Object> response, Exception e) {
        response.put("status", "error");
        if (e instanceof IllegalArgumentException) {
            response.put("message", e.getMessage());
        } else if (e instanceof IOException) {
            response.put("message", "文件处理失败: " + e.getMessage());
        } else if (e instanceof NumberFormatException) {
            response.put("message", "无效的用户凭证");
        } else {
            log.error("操作失败", e);
            response.put("message", "服务器内部错误");
        }
    }

    private void checkFindItemMatches(LostItem newLostItem) {
        List<FindItemDTO> matches = findMapper.selectByFuzzySearch(
                newLostItem.getItemName(),
                newLostItem.getLostLocation(), // 假设Mapper中使用@Param("foundLocation")
                newLostItem.getLostTime(),
                null



        );

        matches.stream()
                .filter(match -> !isNotificationExists(newLostItem.getUserId(), "FOUND", match.getId()))
                .forEach(match -> createNotification(newLostItem, match));
    }

    // LostItemService.java - createNotification 方法
    private void createNotification(LostItem lostItem, FindItemDTO findItem) {
        Notifications notification = Notifications.builder()
                .userId(lostItem.getUserId())
                .title("发现可能的匹配招领信息")
                .content(String.format("您丢失的【%s】可能与用户%s发布的招领信息匹配",
                        lostItem.getItemName(), findItem.getUsername()))
                .relatedType("FOUND")
                .relatedFoundItemId(findItem.getId())
                .build();
        notificationsService.save(notification);
    }

    private boolean isNotificationExists(Long userId, String type, Long itemId) {
        return notificationsService.getByRelatedItem(userId, type, itemId) != null;
    }
    // 新增导入方法
    public int importFromExcel(MultipartFile file) throws Exception {
        int count = 0;
        try (InputStream is = file.getInputStream()) {
            // 获取当前用户ID
            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
            Long userId = Long.parseLong(authentication.getPrincipal().toString());

            List<LostItemDTO> dtos = EasyExcel.read(is)
                    .head(LostItemDTO.class)
                    .sheet()
                    .doReadSync();

            for (LostItemDTO dto : dtos) {
                Map<String, Object> result = addLostItem(
                        dto.getItemName(),
                        dto.getItemCategory(),
                        dto.getLostLocation(),
                        dto.getLocate(),
                        dto.getLostTime(),
                        dto.getDetailedDescription(),
                        null // 图片不导入
                );
                if ("success".equals(result.get("status"))) {
                    count++;
                }
            }
        }
        return count;
    }

    // 修改导出方法
    public ByteArrayOutputStream exportToExcel(List<LostItemDTO> items) throws Exception {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        EasyExcel.write(outputStream, LostItemDTO.class)
                .sheet("失物数据")
                .doWrite(items);
        return outputStream;
    }
}